﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FimetContoDeposito.BLL.Objects;
using FimetContoDeposito.DAL;
using GrayParrot.Core;

namespace FimetContoDeposito.BLL.Facades
{
    public class MovimentoDettaglioFacade : FacadeBase<MovimentoDettaglioFacade>
    {
        FCDContext m_ctx = null;

        public Repository<FCD_MovimentiDettaglio, Guid> Repo { get; internal set; }

        public MovimentoDettaglioFacade()
        {
        }

        public override void Initialize()
        {
            m_ctx = new FCDContext();
            m_ctx.Configuration.LazyLoadingEnabled = false;
            m_ctx.Configuration.ProxyCreationEnabled = false;

            Repo = this.GetRepository<FCD_MovimentiDettaglio, Guid>(m_ctx);
        }

        public override void Dispose()
        {
            if (m_ctx != null)
            {
                m_ctx.Dispose();

                Repo.Dispose();
            }
        }

        public ReturnValue<bool> Add(FCD_MovimentiDettaglio item)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();

            try
            {
                if (item.Id == Guid.Empty)
                {
                    item.Id = Guid.NewGuid();
                }

                this.Repo.Add(item);
                this.Repo.Save();

                retValue.HasValue = true;
                retValue.Value = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> Edit(FCD_MovimentiDettaglio item)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();

            try
            {
                this.Repo.Edit(item);
                this.Repo.Save();

                retValue.HasValue = true;
                retValue.Value = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> Delete(FCD_MovimentiDettaglio item)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();

            try
            {
                this.Repo.Delete(item);
                this.Repo.Save();

                retValue.HasValue = true;
                retValue.Value = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> DeleteAllDetails(Guid idMovimento)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>(false);

            try
            {
                m_ctx.FCD_MovimentiDettaglios.RemoveRange(m_ctx.FCD_MovimentiDettaglios.Where(x=>x.IdMovimento == idMovimento));
                m_ctx.SaveChanges();

                retValue.HasValue = true;
                retValue.Value = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> Delete(Guid id)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();

            try
            {
                var objs = from x in m_ctx.FCD_MovimentiDettaglios
                           where x.Id == id
                           select x;

                if (objs.Any())
                {
                    FCD_MovimentiDettaglio obj = objs.FirstOrDefault();
                    m_ctx.FCD_MovimentiDettaglios.Remove(obj);

                    m_ctx.SaveChanges();

                    retValue.HasValue = true;
                    retValue.Value = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<FCD_MovimentiDettaglio> Get(Guid id)
        {
            ReturnValue<FCD_MovimentiDettaglio> retValue = new ReturnValue<FCD_MovimentiDettaglio>();

            try
            {
                retValue.Value = this.Repo.Get(id);
                retValue.HasValue = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<FCD_MovimentiDettaglio> Get(Guid idMovimento, Guid idArticolo)
        {
            ReturnValue<FCD_MovimentiDettaglio> retValue = new ReturnValue<FCD_MovimentiDettaglio>();

            try
            {
                var objs = from x in m_ctx.FCD_MovimentiDettaglios
                           where x.IdMovimento == idMovimento && x.Articolo == idArticolo
                           select x;

                if (objs.Any())
                {
                    FCD_MovimentiDettaglio obj = objs.FirstOrDefault();

                    retValue.Value = obj;
                    retValue.HasValue = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<IQueryable<FCD_MovimentiDettaglio>> GetAll()
        {
            ReturnValue<IQueryable<FCD_MovimentiDettaglio>> retValue = new ReturnValue<IQueryable<FCD_MovimentiDettaglio>>();
            retValue.HasValue = false;
            retValue.Value = null;

            try
            {
                retValue.Value = this.Repo.GetAll();
                retValue.HasValue = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> SetChiuso(Guid id)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();
            retValue.HasValue = true;
            retValue.Value = false;

            try
            {
                var objs = from x in m_ctx.FCD_MovimentiDettaglios
                          where x.Id == id
                          select x;

                if (objs.Any())
                {
                    FCD_MovimentiDettaglio obj = objs.FirstOrDefault();
                    obj.Chiuso = true;

                    m_ctx.SaveChanges();

                    retValue.Value = true;
                    retValue.HasValue = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        /// <summary>
        /// Imposta le informazioni di contributo...
        /// </summary>
        /// <param name="idElemento">The identifier elemento.</param>
        /// <param name="contributo">The contributo.</param>
        /// <returns></returns>
        public ReturnValue<bool> SetInformazioniContributo(Guid idMovimentoDettaglio, ContributoScarico contributo)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>(false);

            try
            {
                ReturnValue<FCD_MovimentiDettaglio> m_rvMD = this.Get(idMovimentoDettaglio);

                if (m_rvMD.HasValue && m_rvMD.Value != null)
                {
                    m_rvMD.Value.QtaFatt = contributo.QtaFatt;
                    m_rvMD.Value.MovimentoPezzi = contributo.MovimentoPezzi;
                    m_rvMD.Value.MovimentoKg = contributo.MovimentoKg;

                    m_ctx.SaveChanges();

                    retValue.HasValue = true;
                    retValue.Value = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<bool> SetQuantitaDisponibile(Guid id, decimal quantitaDaScaricare)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>();
            retValue.HasValue = true;
            retValue.Value = false;

            try
            {
                var objs = from x in m_ctx.FCD_MovimentiDettaglios
                           where x.Id == id
                           select x;

                if (objs.Any())
                {
                    FCD_MovimentiDettaglio obj = objs.FirstOrDefault();
                    obj.QuantitaDisponibile -= quantitaDaScaricare;

                    if (obj.QuantitaDisponibile == 0)
                    {
                        obj.Chiuso = true;
                    }

                    m_ctx.SaveChanges();

                    retValue.Value = true;
                    retValue.HasValue = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        /// <summary>
        /// Ritorna tutti gli elementi di dettaglio di un movimento...
        /// </summary>
        /// <param name="idMovimento">L'identificatore del movimento</param>
        /// <returns></returns>
        public ReturnValue<IQueryable<FCD_MovimentiDettaglio>> GetDettagliMovimento(Guid idMovimento)
        {
            ReturnValue<IQueryable<FCD_MovimentiDettaglio>> retValue = new ReturnValue<IQueryable<FCD_MovimentiDettaglio>>(null);

            var objs = from x in m_ctx.FCD_MovimentiDettaglios
                       where x.IdMovimento == idMovimento
                       select x;

            if (objs.Any())
            {
                retValue.HasValue = true;
                retValue.Value = objs;
            }

            return retValue;
        }

        /// <summary>
        /// Verifica se i dettagli un un movimento di carico sono utilizzati in movimenti di scarico...
        /// </summary>
        /// <param name="idMovimento">The identifier movimento.</param>
        /// <returns></returns>
        public ReturnValue<bool> CheckDettagliMovimento(Guid idMovimento)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>(false);

            var objs = from x in m_ctx.FCD_MovimentiDettaglios
                       join b in m_ctx.FCD_DettaglioScaricoBollas on x.Id equals b.IdBollaCarico
                       where x.IdMovimento == idMovimento && !b.Cancellato && !x.Cancellato
                       select x;

            if (objs.Any())
            {
                retValue.HasValue = true;
                retValue.Value = true;
            }

            return retValue;
        }

        /// <summary>
        /// Imposta a Cancellato tutti i dettagli di un movimento...
        /// </summary>
        /// <param name="m_id">The m_id.</param>
        /// <returns></returns>
        public ReturnValue<bool> SetCancellato(Guid idMovimento)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>(false);

            try
            {
                m_ctx.SetDettaglioToCancellato(idMovimento);

                retValue.HasValue = true;
                retValue.Value = true;
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        /// <summary>
        /// Imposta a cancellato un singolo elemento del dettaglio di un movimento...
        /// </summary>
        /// <param name="idElemento">The identifier elemento.</param>
        /// <returns></returns>
        public ReturnValue<bool> SetElementoCancellato(Guid idElemento)
        {
            ReturnValue<bool> retValue = new ReturnValue<bool>(false);

            try
            {
                ReturnValue<FCD_MovimentiDettaglio> m_rvMD = this.Get(idElemento);

                if (m_rvMD.HasValue && m_rvMD.Value != null)
                {
                    m_rvMD.Value.Cancellato = true;
                    m_rvMD.Value.DataCancellazione = DateTime.Now;

                    m_ctx.SaveChanges();

                    retValue.HasValue = true;
                    retValue.Value = true;
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }

        public ReturnValue<decimal> GetFLotto(Guid idElemento)
        {
            ReturnValue<decimal> retValue = new ReturnValue<decimal>(0);

            try
            {
                ReturnValue<FCD_MovimentiDettaglio> m_rvMD = this.Get(idElemento);

                if (m_rvMD.HasValue && m_rvMD.Value != null)
                {
                    retValue.HasValue = true;
                    retValue.Value = (m_rvMD.Value.FLotto.HasValue ? m_rvMD.Value.FLotto.Value : 0);
                }
            }
            catch (Exception ex)
            {
                retValue.HasError = true;
                retValue.Error = ex;
            }

            return retValue;
        }
    }
}
